package com.hw.protocol.tool.util;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.crypto.symmetric.AES;

import java.util.Arrays;

/**
 * @author : lihy
 * @date : 2023/8/15 16:36
 * description:
 */

public class CryptoUtil {

    /**
     * AES加密数据，不补位
     *
     * @param data 需要加密的数据
     * @param key  密钥
     * @return 加密后的数据
     */
    public static byte[] encryptNoPadding(byte[] data, byte[] key) {
        AES aes = new AES(Mode.ECB, Padding.NoPadding, key);
        return aes.encrypt(data);
    }


    /**
     * AES解密数据，不补位
     *
     * @param data 需要解密的数据
     * @param key  密钥
     * @return 解密后的数据
     */
    public static byte[] decryptNoPadding(byte[] data, byte[] key) {
        AES aes = new AES(Mode.ECB, Padding.NoPadding, key);
        return aes.decrypt(data);
    }

    /**
     * PKCS5Padding补位后加密
     *
     * @param data 需要加密的数据
     * @param key  密钥
     * @return 加密后的数据
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        AES aes = new AES(Mode.ECB, Padding.PKCS5Padding, key);
        return aes.encrypt(data);
    }

    /**
     * PKCS5Padding补位后解密
     *
     * @param data 加密后的数据
     * @param key  密钥
     * @return 解密后的数据
     */
    public static byte[] decrypt(byte[] data, byte[] key) {
        AES aes = new AES(Mode.ECB, Padding.PKCS5Padding, key);
        return aes.decrypt(data);
    }

    /**
     * HMAC SHA256 加密
     *
     * @param data 需要加密的数据
     * @param key  密钥
     * @return 加密后的数据
     */
    public static byte[] hMacSha256(byte[] data, byte[] key) {
        HMac mac = new HMac(HmacAlgorithm.HmacSHA256, key);
        return mac.digest(data);
    }

    /**
     * 删除填充数据
     *
     * @param bytes 原始数据
     * @return 删除填充后的数据
     */
    public static byte[] stripPadding(byte[] bytes) {
        if (bytes.length < 16 || bytes.length % 16 != 0) {
            return bytes;
        }
        int pad = bytes[bytes.length - 1] & 0xFF;
        if (pad <= 16) {
            int endIndex = bytes.length - pad;
            byte[] padBytes = Arrays.copyOfRange(bytes, endIndex, bytes.length - 1);
            boolean flag = true;
            for (byte b : padBytes) {
                if (b != pad) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                return Arrays.copyOfRange(bytes, 0, endIndex);
            }
        }
        return bytes;
    }

    /**
     * 补位到16的倍数
     *
     * @param bytes 原始数据
     * @return 补位后的数据
     */
    public static byte[] padding(byte[] bytes) {
        if (bytes.length % 16 == 0) {
            return bytes;
        }
        int pad = 16 - bytes.length % 16;
        byte[] padding = new byte[pad];
        for (int i = 0; i < pad; i++) {
            padding[i] = (byte) pad;
        }
        return ArrayUtil.addAll(bytes, padding);
    }
}
